import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONString;
import org.json.JSONStringer;


/***********************************************************************
 * Clock class
 * 
 * Implements a clock that notifies its observers at every tick
 *
 * Signature:
 *  public static Clock create (int initTime);
 *  public void registerObserver (Observer<Integer> obs);
 *  public void tick ();
 ***********************************************************************/

public class Clock implements JSONString {

  private int time;
  private List<Observer<Integer>> observers;

  private Clock (int c) {
    time = c;
    observers = List.empty();
  }

  public static Clock create (int c) {
    return new Clock(c);
  }

  public void registerObserver (Observer<Integer> ob) {
    observers = List.cons(ob,observers);
  }
  
  public int currentTime() {
    return time;
  }
  
  public void tick () {
    time++;
    for (Observer<Integer> obs : observers)
      obs.notify(time);
  }

  public static Clock fromJSON(JSONObject json) {
    try {
      if(json.getString("className").equals("Clock")) {
        return new Clock(json.getInt("time"));
      } else {
        System.err.println("\"" + json.toString() + "\" does not represent a Clock.");
        throw new RuntimeException("Cannot parse JSON, it is not a Clock!");
      }
    } catch (JSONException e) {
      e.printStackTrace();
      throw new RuntimeException("Unrecoverable JSON error, see above stack trace");
    }
    
  }

  @Override
  public String toJSONString() {
    try {
      return new JSONStringer()
                        .object() 
                          .key("className")
                          .value("Clock")
                          .key("time")
                          .value(this.time)
                        .endObject().toString();
    } catch (JSONException e) {
      e.printStackTrace();
      throw new RuntimeException("Unrecoverable JSON error, see above stack trace.");
    }
  }
}